package com.zlsf.publish;

import com.alibaba.fastjson.JSON;
import com.zlsf.flv.FlvEncoder;
import com.zlsf.util.ByteHolder;
import com.zlsf.verticles.msg.MediaChannelMsg;
import com.zlsf.verticles.msg.MediaPublishMessage;
import io.vertx.core.Vertx;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class MediaConverter {

  private static ConcurrentHashMap<String, MediaConverter> converters = new ConcurrentHashMap<>();
  private FlvEncoder flvEncoder;
  ByteHolder buffer;
  Vertx vertx;

  private MediaConverter(Vertx vertx) {
    this.buffer = new ByteHolder(2048 * 100);
    this.flvEncoder = new FlvEncoder(true, true);
    this.vertx = vertx;
  }

  public static MediaConverter create(String router, Vertx vertx) {
    return converters.computeIfAbsent(router, (k) -> new MediaConverter(vertx));
  }

  public static void close(String router) {
    MediaConverter converter = converters.remove(router);
    if (converter != null) {
      converter = null;
      log.info("注销解码器");
    }
  }


  /**
   * 解码
   *
   * @param msg
   */
  public void convert(MediaChannelMsg msg) {

  }

  /**
   * 转码视频
   *
   * @param msg
   */
  private void doConvertVideo(MediaChannelMsg msg) {
    this.buffer.write(msg.getH264());
    while (true) {
      byte[] nalu = readNalu();
      if (nalu == null) break;
      if (nalu.length < 4) continue;

      byte[] flvTag = this.flvEncoder.write(nalu, (int) (msg.getTimeStmp() - msg.getFirstTime()));

      if (flvTag == null) continue;
      MediaPublishMessage publishMessage = new MediaPublishMessage();
      publishMessage.setData(flvTag);
      publishMessage.setTs(msg.getTimeStmp());
      publishMessage.setReady(this.flvEncoder.videoReady());
      publishMessage.setFt(msg.getFirstTime());
      publishMessage.setFlvHeader(this.flvEncoder.getHeader());
      publishMessage.setVideoHeader(this.flvEncoder.getVideoHeader());
      publishMessage.setIframe(this.flvEncoder.getLastIFrame());
      this.vertx.eventBus().publish(msg.getTag(), JSON.toJSONString(publishMessage));
    }
  }


  private byte[] readNalu() {
    for (int i = 0; i < buffer.size() - 3; i++) {
      int a = buffer.get(i + 0) & 0xff;
      int b = buffer.get(i + 1) & 0xff;
      int c = buffer.get(i + 2) & 0xff;
      int d = buffer.get(i + 3) & 0xff;
      if (a == 0x00 && b == 0x00 && c == 0x00 && d == 0x01) {
        if (i == 0) continue;
        byte[] nalu = new byte[i];
        buffer.sliceInto(nalu, i);
        return nalu;
      }
    }
    return null;
  }
}
